package ui.component;

import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TextField;
import javafx.scene.control.TreeCell;
import javafx.scene.control.TreeItem;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import ui.DatabaseHandler;

/**
 *
 * @author Merli András-Bertalan
 */
public final class TextFieldTreeCell extends TreeCell<String> {

    private final DatabaseHandler databaseHandler;
    private TextField textField;
    private final ContextMenu databasesMenu = new ContextMenu();
    private final ContextMenu tablesMenu = new ContextMenu();
    private final ContextMenu databaseMenu = new ContextMenu();
    private final ContextMenu tableMenu = new ContextMenu();

    public TextFieldTreeCell(final DatabaseHandler databaseHandler) {
        this.databaseHandler = databaseHandler;
        MenuItem addDatabaseMenuItem = new MenuItem("Add Database");
        databasesMenu.getItems().add(addDatabaseMenuItem);
        addDatabaseMenuItem.setOnAction(new EventHandler() {
            @Override
            public void handle(Event t) {
                TreeItem newDatabase =
                        new TreeItem<>("New Database");
                TreeItem newTablesNode =
                        new TreeItem<>("Tables");
                newDatabase.getChildren().add(newTablesNode);
                getTreeItem().getChildren().add(newDatabase);
                databaseHandler.addDatabase("New Database");
            }
        });

        MenuItem addTableMenuItem = new MenuItem("Add Table");
        tablesMenu.getItems().add(addTableMenuItem);
        addTableMenuItem.setOnAction(new EventHandler() {
            @Override
            public void handle(Event t) {
                TreeItem newTable =
                        new TreeItem<>("New Table");
                getTreeItem().getChildren().add(newTable);
                databaseHandler.addTableToDatabase(getTreeItem().getParent().getValue(), "New Table");
            }
        });

        MenuItem deleteDatabaseMenuItem = new MenuItem("Delete Database");
        databaseMenu.getItems().add(deleteDatabaseMenuItem);
        deleteDatabaseMenuItem.setOnAction(new EventHandler() {
            @Override
            public void handle(Event t) {
                databaseHandler.deleteDatabase(getTreeItem().getValue());
                getTreeItem().getParent().getChildren().remove(getTreeItem());
            }
        });

        MenuItem deleteTableMenuItem = new MenuItem("Delete Table");
        tableMenu.getItems().add(deleteTableMenuItem);
        deleteTableMenuItem.setOnAction(new EventHandler() {
            @Override
            public void handle(Event t) {
                databaseHandler.deleteTableFromDatabase(getTreeItem().getParent().getParent().getValue(), getTreeItem().getValue());
                getTreeItem().getParent().getChildren().remove(getTreeItem());
            }
        });

//        MenuItem editTableContentMenuItem = new MenuItem("Edit Table Content");
//        tableMenu.getItems().add(editTableContentMenuItem);
//        editTableContentMenuItem.setOnAction(new EventHandler() {
//            @Override
//            public void handle(Event t) {
//                databaseHandler.set
//            }
//        });
    }

    @Override
    public void startEdit() {
        super.startEdit();

        if (textField == null) {
            createTextField();
        }
        setText(null);
        setGraphic(textField);
        textField.selectAll();
    }

    @Override
    public void cancelEdit() {
        super.cancelEdit();

        setText((String) getItem());
        setGraphic(getTreeItem().getGraphic());
    }

    @Override
    public void updateItem(String item, boolean empty) {
        super.updateItem(item, empty);

        if (empty) {
            setText(null);
            setGraphic(null);
        } else {
            if (isEditing()) {
                if (textField != null) {
                    textField.setText(getString());
                }
                setText(null);
                setGraphic(textField);
            } else {
                String previousText = getText();
                String currentText = getString();
                setText(getString());
                setGraphic(getTreeItem().getGraphic());
                TreeItem treeItem = getTreeItem();
                if ("Databases".equals(treeItem.getValue())) {
                    setContextMenu(databasesMenu);
                } else if ("Tables".equals(treeItem.getValue())) {
                    setContextMenu(tablesMenu);
                } else if (treeItem.getParent() != null) {
                    if ("Databases".equals(treeItem.getParent().getValue())) {
                        setContextMenu(databaseMenu);
                        if (previousText != null) {
                            databaseHandler.renameDatabase(previousText, currentText);
                        }
                    } else if ("Tables".equals(treeItem.getParent().getValue())) {
                        setContextMenu(tableMenu);
                        if (previousText != null) {
                            databaseHandler.renameTable((String) treeItem.getParent().getParent().getValue(), previousText, currentText);
                        }
                    }
                }
            }
        }
    }

    private void createTextField() {
        textField = new TextField(getString());
        textField.setOnKeyReleased(new EventHandler<KeyEvent>() {
            @Override
            public void handle(KeyEvent t) {
                if (t.getCode() == KeyCode.ENTER) {
                    commitEdit(textField.getText());
                } else if (t.getCode() == KeyCode.ESCAPE) {
                    cancelEdit();
                }
            }
        });

    }

    private String getString() {
        return getItem() == null ? "" : getItem().toString();
    }
}
